/*
 * Copyright 2013 Aliyun.com All right reserved. This software is the
 * confidential and proprietary information of Aliyun.com ("Confidential
 * Information"). You shall not disclose such Confidential Information and shall
 * use it only in accordance with the terms of the license agreement you entered
 * into with Aliyun.com .
 */
package com.mtauto.service;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Properties;

import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.VelocityEngine;

import com.mtauto.model.Apk;

/**
 * @author <a href="mailto:li.jinl@alibaba-inc.com">Stone.J</a> Nov 21, 2013
 */
public class ApkService {

    private Collection<Apk> apks                   = new ArrayList<Apk>();
    private String          mtautoHome;
    private static String   FILE_PATH_SPLIT_SYMBOL = "/";
    private String          sdkDir;
    private String          toolsDir;
    private String          javaHome;

    public static String    targetPackage;

    public String getMtautoHome() {
        return mtautoHome;
    }

    public String getSdkDir() {
        return sdkDir;
    }

    public String getJavaHome() {
        return javaHome;
    }

    public String getToolsDir() {
        return toolsDir;
    }

    public void setJavaHome(String javaHome) {
        this.javaHome = javaHome;
    }

    public void setToolsDir(String toolsDir) {
        this.toolsDir = toolsDir;
    }

    public void setSdkDir(String sdkDir) {
        this.sdkDir = sdkDir;
    }

    public void setMtautoHome(String mtautoHome) {
        this.mtautoHome = mtautoHome;
    }

    public Collection<Apk> getApks() {
        return new ArrayList<Apk>(apks);
    }

    public void setApkInfo(String apkInfo) {
        if (apkInfo == null || apkInfo.isEmpty()) {
            return;
        }
        for (String value : apkInfo.trim().split(";")) {
            String[] info = value.split("#");
            Apk apk = new Apk();
            apk.setName(info[0].trim());
            apk.setTitle(info[1].trim());
            apk.setFile(info[2].trim());
            this.apks.add(apk);
        }
    }

    public void genRecordApk(String targetPackage, String lantchActivityClass) throws Exception {
        mergeTemplate(targetPackage, lantchActivityClass);
        genApk();
    }

    private void genApk() throws Exception {
        step0();
        step1();
        setup2();
        setup3();
        setup4();
        setup5();
        setup6();
    }

    private void step0() throws Exception {
        execCMD("sh " + mtautoHome + "/cafeTest/install/rm.sh " + mtautoHome
                + "/cafeTest/bin/classes/");
        execCMD("rm -rf " + mtautoHome + "/cafeTest/cafeTest/bin/cafeTestSign.apk");
        execCMD("rm -rf " + mtautoHome + "/cafeTest/cafeTest/bin/cafeTest.apk");
        execCMD("rm -rf " + mtautoHome + "/cafeTest/cafeTest/bin/classes.dex");
        execCMD("rm -rf " + mtautoHome + "/cafeTest/cafeTest/bin/resources.ap_");

    }

    private void setup6() throws Exception {
        execCMD("sh " + mtautoHome + "/cafeTest/install/step6.sh " + javaHome + " " + mtautoHome);

    }

    private void setup5() throws Exception {
        execCMD("sh " + mtautoHome + "/cafeTest/install/step5.sh " + sdkDir + " " + mtautoHome);

    }

    private void setup4() throws Exception {
        execCMD("sh " + mtautoHome + "/cafeTest/install/step4.sh " + toolsDir + " " + mtautoHome
                + " " + sdkDir);
    }

    private void setup3() throws Exception {
        execCMD("sh " + mtautoHome + "/cafeTest/install/step3.sh " + mtautoHome + " " + toolsDir);
    }

    private void setup2() throws Exception {
        execCMD("sh " + mtautoHome + "/cafeTest/install/step2.sh " + sdkDir + " " + mtautoHome
                + " " + javaHome);
    }

    private void step1() throws Exception {
        execCMD("sh " + mtautoHome + "/cafeTest/install/step1.sh " + mtautoHome + " " + sdkDir
                + " " + toolsDir);
    }

    public static void execCMD(String cmd) throws Exception {

        Process p = Runtime.getRuntime().exec(cmd);
        final InputStream stdout = p.getInputStream();
        final InputStream errStdout = p.getErrorStream();
        byte[] buf = new byte[1024];
        int len = 0;
        try {
            while ((len = stdout.read(buf)) != -1) {
                System.out.println(new String(buf, 0, len));
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                stdout.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        len = 0;
        try {
            while ((len = errStdout.read(buf)) != -1) {
                System.out.println(new String(buf, 0, len));
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                errStdout.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    public static Process asyncExecCMD(String cmd) throws Exception {

        Process p = Runtime.getRuntime().exec(cmd);
        final InputStream stdout = p.getInputStream();
        final InputStream errStdout = p.getErrorStream();
        new Thread(new Runnable() {

            public void run() {
                byte[] buf = new byte[1024];
                int len = 0;
                try {
                    while ((len = stdout.read(buf)) != -1) {
                        System.out.println(new String(buf, 0, len));
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                } finally {
                    try {
                        stdout.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }).start();

        new Thread(new Runnable() {

            public void run() {
                byte[] buf = new byte[1024];
                int len = 0;
                try {
                    while ((len = errStdout.read(buf)) != -1) {
                        System.out.println(new String(buf, 0, len));
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                } finally {
                    try {
                        errStdout.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }).start();
        return p;
    }

    private void mergeTemplate(String targetPackage, String lantchActivityClass) throws Exception {
        VelocityEngine ve = new VelocityEngine();
        VelocityContext vc = new VelocityContext();
        vc.put("targetPackage", targetPackage);
        vc.put("lantchActivityClass", lantchActivityClass);
        Properties p = new Properties();
        p.setProperty("file.resource.loader.path", mtautoHome);
        ve.init(p);
        String xmlTemp = "cafeTest" + FILE_PATH_SPLIT_SYMBOL + "AndroidManifest.xml.vm";
        String toXmlTemp = mtautoHome + FILE_PATH_SPLIT_SYMBOL + "cafeTest"
                + FILE_PATH_SPLIT_SYMBOL + "AndroidManifest.xml";
        String javaTemp = "cafeTest/src/org/codeanywhere/cafe/test" + FILE_PATH_SPLIT_SYMBOL
                + "TestCafeRecord.java.vm";
        String toJavaTemp = mtautoHome + FILE_PATH_SPLIT_SYMBOL
                + "cafeTest/src/org/codeanywhere/cafe/test" + FILE_PATH_SPLIT_SYMBOL
                + "TestCafeRecord.java";
        Writer toXmlTempWriter = new OutputStreamWriter(new FileOutputStream(toXmlTemp));
        Writer toJavaTempWriter = new OutputStreamWriter(new FileOutputStream(toJavaTemp));
        ve.mergeTemplate(xmlTemp, "utf-8", vc, toXmlTempWriter);
        ve.mergeTemplate(javaTemp, "utf-8", vc, toJavaTempWriter);
        toXmlTempWriter.close();
        toJavaTempWriter.close();
    }

    public void signApk(Apk apk) throws Exception {
        targetPackage = apk.getName();
        String installDir = getInstallDir(apk.getFile());
        execCMD("sh " + mtautoHome + "/cafeTest/install/rm.sh " + installDir);
        execCMD("unzip -d" + installDir + " " + apk.getFile());
        execCMD("rm -rf " + installDir + "/assets");
        execCMD("rm -rf " + installDir + "/META-INF");
        execCMD("sh " + mtautoHome + "/cafeTest/install/zip.sh 1.zip " + installDir);
        execCMD("mv " + installDir + "/1.zip " + installDir + "/OfficeAssistant.apk");
        execCMD("sh " + mtautoHome + "/cafeTest/install/sign.sh " + javaHome + " " + mtautoHome
                + " " + installDir + "/OfficeAssistantSign.apk" + " " + installDir
                + "/OfficeAssistant.apk");
        apk.setFile(installDir + "/OfficeAssistantSign.apk");
    }

    private String getInstallDir(String file) {
        String[] strs = file.split("/");
        return file.substring(0, file.length() - strs[strs.length - 1].length()) + "/install/";
    }

    public static void main(String args[]) throws Exception {
        ApkService as = new ApkService();
        as.setMtautoHome("/Users/chenke/Documents/javawork/mtauto");
        as.setSdkDir("/Users/chenke/softs/adt/sdk/");
        as.setToolsDir("/Users/chenke/softs/adt/sdk/platform-tools/");
        as.setJavaHome("/usr/");
        as.genRecordApk("com.pubinfo.officeassistant", "com.pubinfo.hongshi.activity.LoginActivity");

    }
}
